package com.mutual.assistance.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.mutual.assistance.exception.BizException;
import com.mutual.assistance.exception.code.ExceptionCode;
import com.mutual.assistance.user.converter.UserConverterParams;
import com.mutual.assistance.user.mapper.MenuMapper;
import com.mutual.assistance.user.model.dto.MenuDTO;
import com.mutual.assistance.user.model.dto.MenusDTO;
import com.mutual.assistance.user.model.po.MenuPO;
import com.mutual.assistance.user.model.vo.AddMenuVO;
import com.mutual.assistance.user.model.vo.UpdateMenuVO;
import com.mutual.assistance.user.service.AuthorityMenuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenyuxin
 * @version 1.0
 * @description 权限服务实现类
 * @date 2023/4/17 16:41
 */
@Service
@Slf4j
public class AuthorityMenuServiceImpl implements AuthorityMenuService {

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private UserConverterParams authConverterParams;

    @Resource
    private AuthorityMenuService authorityMenuService;

    @Override
    public boolean addMenu(AddMenuVO addMenuVO) {
        if (addMenuVO == null) {
            log.error("请求参数为空");
            throw BizException.wrap(ExceptionCode.INVALID_OBJECT.getCode(), ExceptionCode.INVALID_OBJECT.getMsg());
        }

        log.info("请求传入参数：{}", addMenuVO);

        String code = addMenuVO.getCode();
        log.info("传入参数code：{}", code);
        MenuPO menuPODB = menuMapper.selectOne(new LambdaQueryWrapper<MenuPO>().eq(MenuPO::getCode, code));
        if (menuPODB != null) {
            log.info("{}, 已存在，请勿重复添加", menuPODB.getCode());
            throw new BizException(ExceptionCode.REPEAT_ADDITION.getCode(), ExceptionCode.REPEAT_ADDITION.getMsg());
        }

        String pId = addMenuVO.getPId();
        log.info("传入参数pId：{}", pId);

        MenuPO menuParent = checkMenuIsExist(pId);
        log.info("父节点数据：{}", menuParent);

        MenuPO menuPO = authConverterParams.addMenuVO2MenuPO(addMenuVO);
        log.info("转换：{}", menuPO);

        Boolean isMenu = addMenuVO.getIsMenu();
        if (isMenu) {
            menuPO.setIsMenu(1);
            menuPO.setLevel(2);
            menuPO.setSort(3);
        } else {
            menuPO.setIsMenu(0);
            menuPO.setLevel(3);
            menuPO.setSort(4);
        }

        log.info("插入数据库数据：{}", menuPO);
        int insert = menuMapper.insert(menuPO);

        if (insert < 0) {
            log.error("数据库插入数据失败，{}", menuPO);
            throw BizException.wrap(ExceptionCode.SQL_EX.getCode(), ExceptionCode.SQL_EX.getMsg());
        }

        return true;
    }

    @NotNull
    private MenuPO checkMenuIsExist(String id) {
        MenuPO menuParent = menuMapper.selectOne(new LambdaQueryWrapper<MenuPO>().eq(MenuPO::getId, id));
        if (menuParent == null) {
            log.error("{}不存在，请重新发送", id);
            throw BizException.wrap(ExceptionCode.DATABASE_FIELD_DOES_NOT_EXIST.getCode(),
                    ExceptionCode.DATABASE_FIELD_DOES_NOT_EXIST.getMsg() + ": " + id);
        }
        return menuParent;
    }

    @Override
    public boolean addMenus(List<AddMenuVO> menuVOs) {
        if (CollectionUtils.isEmpty(menuVOs)) {
            log.error("请求参数为空");
            throw BizException.wrap(ExceptionCode.INVALID_OBJECT.getCode(), ExceptionCode.INVALID_OBJECT.getMsg());
        }

        for (AddMenuVO menuVO : menuVOs) {
            if (!addMenu(menuVO)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean deleteMenu(String id) {
        log.info("要删除的菜单资源id为：{}", id);
        int delete = menuMapper.deleteById(id);
        return delete > 0;
    }

    @Override
    public boolean deleteMenus(List<String> menuIds) {
        if (CollectionUtils.isEmpty(menuIds)) {
            log.error("请求参数为空");
            throw BizException.wrap(ExceptionCode.INVALID_OBJECT.getCode(), ExceptionCode.INVALID_OBJECT.getMsg());
        }
        int deleteBatchIds = menuMapper.deleteBatchIds(menuIds);
        return deleteBatchIds > 0;
    }

    @Override
    public boolean updateMenu(UpdateMenuVO updateMenuVO) {
        if (updateMenuVO == null) {
            log.error("请求参数为空");
            throw BizException.wrap(ExceptionCode.INVALID_OBJECT.getCode(), ExceptionCode.INVALID_OBJECT.getMsg());
        }

        log.info("请求传入的参数为：{}", updateMenuVO);
        String menuId = updateMenuVO.getMenuId();
        log.info("菜单主键：{}", menuId);
        checkMenuIsExist(menuId);
        MenuPO menuPO = authConverterParams.updateMenuVO2MenuPO(updateMenuVO);
        log.info("实体类转换：{}", menuPO);

        if (!StringUtils.isEmpty(menuPO.getStatus())) {
            menuPO.setStatus("1");
        }

        int update = menuMapper.update(menuPO, new LambdaQueryWrapper<MenuPO>().eq(MenuPO::getId, menuPO.getId()));
        if (update < 0) {
            log.error("数据库更新数据失败，{}", menuPO);
            throw BizException.wrap(ExceptionCode.SQL_EX.getCode(), ExceptionCode.SQL_EX.getMsg());
        }
        return true;
    }

    @Override
    public MenuDTO getMenu(String menuId) {
        log.info("菜单主键id：{}", menuId);
        MenuPO menuPO = checkMenuIsExist(menuId);
        log.info("获取到：{}", menuPO);
        return authConverterParams.menuPO2MenuDTO(menuPO);
    }

    @Override
    public List<MenuDTO> getMenus() {
        return getMenuDTOList(null, false);
    }

    @Override
    public MenusDTO getMenusByLevel() {
        MenuPO menuPO = menuMapper.selectOne(new LambdaQueryWrapper<MenuPO>().eq(MenuPO::getId, 0));
        log.info("获取到根目录：{}", menuPO);
        if (menuPO == null) {
            return null;
        }
        log.info("开始调用递归");
        return authorityMenuService.recursionGetMenus(menuPO.getId());
    }

    @Override
    public List<MenuDTO> getMenusBySort() {
        return getMenuDTOList(null, true);
    }

    /**
     * @param menuId 菜单主键
     * @return 层级菜单资源
     * @description 递归获取所有菜单资源
     * @author chenyuxin
     * @date 2023/4/19 10:53
     */
    @Transactional
    public MenusDTO recursionGetMenus(String menuId) {
        // 递归终止条件
        if (menuId == null) {
            return null;
        }
        // 获取所有该菜单id的子级
        List<MenuDTO> menuDTOList = getMenuDTOList(menuId, false);
        List<MenusDTO> list = new ArrayList<>();

        if (menuDTOList == null) {
            return null;
        }

        // 子级向下递归
        for (MenuDTO menuDTO : menuDTOList) {
            MenusDTO menus = authorityMenuService.recursionGetMenus(menuDTO.getId());
            list.add(menus);
        }

        // 获取当前菜单其他数据
        MenuDTO menuDTO = getMenu(menuId);
        // 调用转换
        MenusDTO menusDTO = authConverterParams.menuDTO2MenusDTO(menuDTO);
        menusDTO.setMenuDTOList(list);

        return menusDTO;
    }

    @Nullable
    private List<MenuDTO> getMenuDTOList(String menuId, boolean sort) {
        log.info("菜单主键：{}", menuId);
        LambdaQueryWrapper<MenuPO> queryWrapper = new LambdaQueryWrapper<MenuPO>()
                .eq(MenuPO::getStatus, 1)
                .eq(menuId != null, MenuPO::getPId, menuId);

        if (sort) {
            queryWrapper.orderByAsc(MenuPO::getSort);
        }

        List<MenuPO> menuPOs = menuMapper.selectList(queryWrapper);

        if (menuPOs == null) {
            return null;
        }

        log.info("获取所有数据成功");
        List<MenuDTO> list = new ArrayList<>();

        for (MenuPO menuPO : menuPOs) {
            MenuDTO menuDTO = authConverterParams.menuPO2MenuDTO(menuPO);
            if (menuDTO != null) {
                log.info("转换成功：{} to {}", menuPO, menuDTO);
                list.add(menuDTO);
            }
        }

        return list;
    }

}
